from typing import Dict, List, Tuple, Optional
from chess.pieces import Piece, King, Queen, Rook, Bishop, Knight, Pawn

class Board:
    def __init__(self):
        """
        初始化棋盘
        创建一个8x8的棋盘并设置初始棋子
        """
        self.squares = {}  # 用字典存储棋子位置，键为(row, col)，值为棋子对象
        self.setup_pieces()
        
        # 记录国王位置，便于检查将军
        self.white_king_position = (7, 4)  # 白方国王初始位置
        self.black_king_position = (0, 4)  # 黑方国王初始位置
        
        # 记录被吃掉的棋子
        self.captured_pieces = {
            'white': [],
            'black': []
        }
        
        # 记录上一步移动，用于吃过路兵判断
        self.last_move = None
    
    def setup_pieces(self):
        """
        设置棋盘初始棋子
        按照国际象棋规则放置所有棋子
        """
        # 放置黑方棋子 (顶部)
        self.place_piece(Rook('black', (0, 0)))
        self.place_piece(Knight('black', (0, 1)))
        self.place_piece(Bishop('black', (0, 2)))
        self.place_piece(Queen('black', (0, 3)))
        self.place_piece(King('black', (0, 4)))
        self.place_piece(Bishop('black', (0, 5)))
        self.place_piece(Knight('black', (0, 6)))
        self.place_piece(Rook('black', (0, 7)))
        
        # 放置黑方兵
        for col in range(8):
            self.place_piece(Pawn('black', (1, col)))
        
        # 放置白方棋子 (底部)
        self.place_piece(Rook('white', (7, 0)))
        self.place_piece(Knight('white', (7, 1)))
        self.place_piece(Bishop('white', (7, 2)))
        self.place_piece(Queen('white', (7, 3)))
        self.place_piece(King('white', (7, 4)))
        self.place_piece(Bishop('white', (7, 5)))
        self.place_piece(Knight('white', (7, 6)))
        self.place_piece(Rook('white', (7, 7)))
        
        # 放置白方兵
        for col in range(8):
            self.place_piece(Pawn('white', (6, col)))
    
    def place_piece(self, piece: Piece):
        """
        在指定位置放置棋子
        :param piece: 要放置的棋子
        """
        self.squares[piece.position] = piece
    
    def get_piece_at(self, position: Tuple[int, int]) -> Optional[Piece]:
        """
        获取指定位置的棋子
        :param position: 位置坐标
        :return: 该位置的棋子对象，如果没有则返回None
        """
        return self.squares.get(position)
    
    def remove_piece_at(self, position: Tuple[int, int]) -> Optional[Piece]:
        """
        移除指定位置的棋子
        :param position: 位置坐标
        :return: 被移除的棋子对象，如果没有则返回None
        """
        if position in self.squares:
            return self.squares.pop(position)
        return None
    
    def move_piece(self, from_pos: Tuple[int, int], to_pos: Tuple[int, int]) -> bool:
        """
        移动棋子
        :param from_pos: 起始位置
        :param to_pos: 目标位置
        :return: 移动是否成功
        """
        piece = self.get_piece_at(from_pos)
        if piece is None:
            return False
        
        # 检查目标位置的棋子
        target_piece = self.get_piece_at(to_pos)
        
        # 如果目标位置有棋子且是同色，则不能移动
        if target_piece is not None and target_piece.color == piece.color:
            return False
        
        # 吃子逻辑
        if target_piece is not None:
            self.captured_pieces[target_piece.color].append(target_piece)
        
        # 记录吃过路兵前的状态
        en_passant_capture = False
        en_passant_pos = None
        
        # 处理吃过路兵
        if isinstance(piece, Pawn):
            from_row, from_col = from_pos
            to_row, to_col = to_pos
            
            # 判断是否为吃过路兵：斜向移动到空位置
            if from_col != to_col and target_piece is None:
                # 吃过路兵位置在目标位置同列、起始位置同行
                en_passant_pos = (from_row, to_col)
                en_passant_piece = self.get_piece_at(en_passant_pos)
                
                if en_passant_piece is not None and isinstance(en_passant_piece, Pawn):
                    self.captured_pieces[en_passant_piece.color].append(en_passant_piece)
                    self.remove_piece_at(en_passant_pos)
                    en_passant_capture = True
        
        # 更新国王位置
        if isinstance(piece, King):
            if piece.color == 'white':
                self.white_king_position = to_pos
            else:
                self.black_king_position = to_pos
        
        # 记录这一步移动
        self.last_move = {
            'piece': piece,
            'from': from_pos,
            'to': to_pos,
            'captured': target_piece,
            'en_passant_capture': en_passant_capture,
            'en_passant_pos': en_passant_pos
        }
        
        # 更新棋子状态和位置
        self.remove_piece_at(from_pos)
        piece.move(to_pos)
        self.place_piece(piece)
        
        # 处理兵的升变 (在Game类中实现)
        
        # 处理过路兵状态
        # 重置所有兵的过路兵状态
        for pos, p in self.squares.items():
            if isinstance(p, Pawn):
                p.en_passant_vulnerable = False
        
        # 如果是兵首次移动两格，标记为可以被吃过路兵
        if isinstance(piece, Pawn):
            from_row, _ = from_pos
            to_row, _ = to_pos
            if abs(from_row - to_row) == 2:  # 移动了两格
                piece.en_passant_vulnerable = True
        
        return True
    
    def get_all_pieces(self, color: str = None) -> List[Piece]:
        """
        获取所有棋子或指定颜色的所有棋子
        :param color: 棋子颜色，如果为None则返回所有棋子
        :return: 棋子列表
        """
        if color is None:
            return list(self.squares.values())
        return [piece for piece in self.squares.values() if piece.color == color]
    
    def is_square_under_attack(self, position: Tuple[int, int], by_color: str) -> bool:
        """
        检查指定位置是否被某一方的棋子攻击
        :param position: 要检查的位置
        :param by_color: 攻击方的颜色
        :return: 如果该位置被攻击则返回True，否则返回False
        """
        for piece in self.get_all_pieces(by_color):
            possible_moves = piece.get_possible_moves(self)
            if position in possible_moves:
                return True
        return False
    
    def is_king_in_check(self, color: str) -> bool:
        """
        检查指定颜色的国王是否被将军
        :param color: 国王颜色
        :return: 如果国王被将军则返回True，否则返回False
        """
        king_position = self.white_king_position if color == 'white' else self.black_king_position
        return self.is_square_under_attack(king_position, 'black' if color == 'white' else 'white')
    
    def clear(self):
        """
        清空棋盘
        """
        self.squares = {}
        self.captured_pieces = {'white': [], 'black': []}
        self.last_move = None 